﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using BlobTowerDefense.Game_Entities;
using Matrix = Microsoft.Xna.Framework.Matrix;

namespace BlobTowerDefense.Managers
{
    public enum ENEMYTYPE { ball1, cube, ball2, spikedBall, ring }

    /// <summary>
    /// Struktura uchovavajici promenna data o nepratelich v zavislosti na typu nepritele
    /// </summary>
    public struct EnemyStats
    {
        public ENEMYTYPE EnemyType;
        public int Hp;
        public int Armor;
        public int MoneyForKilling;
        public float Speed;
        public string PathToModel;

        public EnemyStats(ENEMYTYPE enemyType, int hp, int armor, int moneyForKilling, float speed, string pathToModel)
        {
            this.EnemyType = enemyType;
            this.Hp = hp;
            this.Armor = armor;
            this.MoneyForKilling = moneyForKilling;
            this.Speed = speed;
            this.PathToModel = pathToModel;
        }
    }

    public class EnemyManager
    {
        public static Dictionary<ENEMYTYPE, EnemyStats> DefaultEnemies = new Dictionary<ENEMYTYPE, EnemyStats>(4)
        {
            { ENEMYTYPE.ball1, new EnemyStats(ENEMYTYPE.ball1, 50, 0, 50, 1.0f, "Models/Enemies/enemy1") },
            { ENEMYTYPE.ball2, new EnemyStats(ENEMYTYPE.ball2, 100, 0, 100, 1.0f, "Models/Enemies/enemy2") },
            { ENEMYTYPE.cube, new EnemyStats(ENEMYTYPE.cube, 100, 5, 100, 1.5f, "Models/Enemies/enemy2") },
            { ENEMYTYPE.ring, new EnemyStats(ENEMYTYPE.ring, 150, 5, 100, 1.5f, "Models/Enemies/enemy2") },
            { ENEMYTYPE.spikedBall, new EnemyStats(ENEMYTYPE.spikedBall, 200, 5, 100, 2.0f, "Models/Enemies/enemy2") }
        };

        public List<EnemyEntity> Enemies { get; private set; }

        private float internalTime;
        private const float addTime = 0.5f;
        private const int specialAttackDamage = 50;
        private WaveManager waveManager;

        public EnemyManager()
        {
            this.Enemies = new List<EnemyEntity>();
            waveManager = new WaveManager();
        }

        public void Update()
        {
            if (waveManager.WaveRunning())
            {
                internalTime += addTime;

                float? timeToLaunchNextEnemy = waveManager.TimeToLaunchNextEnemy();
                if (timeToLaunchNextEnemy != null)
                {
                    if (internalTime >= timeToLaunchNextEnemy)
                    {
                        EnemyEntity enemyToAdd = waveManager.GetNextEnemy();
                        if (enemyToAdd != null)
                        {
                            Enemies.Add(enemyToAdd);
                        }
                    }
                }
                waveManager.Update();
                UpdateEnemies();
            }
            else
            {
                if (waveManager.WaveEnded())
                {
                    this.Enemies.Clear();
                }
                internalTime = 0.0f;
            }
        }

        private void UpdateEnemies()
        {
            for (int i = 0; i < Enemies.Count; i++)
            {
                if (Enemies[i] != null)
                {
                    Enemies[i].Update();
                    if (Enemies[i].IsAlive == false)
                    {
                        Enemies.RemoveAt(i);
                    }
                }
            }
        }


        public void Draw()
        {
            DrawEnemies();
        }

        private void DrawEnemies()
        {
            foreach (EnemyEntity enemy in Enemies)
            {
                enemy.Draw();
            }
        }

        public void AddEnemy(ENEMYTYPE enemyType, string worldName, DIFFICULTY difficulty)
        {
            EnemyStats addingEnemy = DefaultEnemies[enemyType];
            switch (difficulty)
            {
                case DIFFICULTY.Easy:
                    addingEnemy.Armor -= (addingEnemy.Armor / 10);
                    addingEnemy.Hp -= (addingEnemy.Hp / 10);
                    addingEnemy.MoneyForKilling += (addingEnemy.MoneyForKilling / 5);
                    break;
                case DIFFICULTY.Medium:
                    break;
                case DIFFICULTY.Hard:
                    addingEnemy.Armor += (addingEnemy.Armor / 10);
                    addingEnemy.Hp += (addingEnemy.Hp / 10);
                    addingEnemy.MoneyForKilling -= (addingEnemy.MoneyForKilling / 5);
                    break;
                default:
                    addingEnemy.Armor -= (addingEnemy.Armor / 10);
                    addingEnemy.Hp -= (addingEnemy.Hp / 10);
                    addingEnemy.MoneyForKilling += (addingEnemy.MoneyForKilling / 5);
                    break;
            }
            Enemies.Add(new EnemyEntity(addingEnemy, PathManager.DefaultPaths[worldName]));
        }

        public bool NextWave()
        {
            return this.waveManager.NextWave();
        }

        public void LaunchWave()
        {
            this.waveManager.LaunchWave();
            Enemies.Add(waveManager.GetNextEnemy());
        }

        public WAVETYPE? GetCurrentWaveType()
        {
            if (this.waveManager == null)
            {
                return null;
            }
            else
            {
                if (WaveManager.CurrentWave == null)
                {
                    return null;
                }
                else
                {
                    return WaveManager.CurrentWave.WaveType;
                }
            }
        }

        public bool WaveRunning()
        {
            return waveManager.WaveRunning();
        }

        public bool WaveEnded()
        {
            if ((Enemies.Count == 0) && waveManager.WaveEnded())
            {
                waveManager.PauseWave();
                return true;
            }
            else
            {
                return false;
            }
        }

        public void SpecialAttack()
        {
            foreach (EnemyEntity enemy in this.Enemies)
            {
                enemy.ReduceHP(specialAttackDamage);
            }
        }
    }
}
